package com.daji.concurrency.multithread_lock;

import java.util.Arrays;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/*
    非常重要，操作系统的读写锁（读者，写者问题）！！！！！
    有些时候我们希望读临界区时可以多线程并发，而写临界区的时候独占。这就是读写锁的应用场景。
    允许多个线程同时读，但只要有一个线程在写，其他线程就必须等待
*/
public class C02_ReadWriteLock {
    public static void main(String[] args) {
        Thread readThread = new Thread(()->{
            Counter counter = new Counter();
            counter.inc(1);
            counter.inc(2);
            counter.inc(3);

        });
        readThread.start();
        Thread whiteThread = new Thread(()->{
            Counter counter = new Counter();
        });
        whiteThread.start();

    }

}

//使用ReentrantLock的过度保护(不管读写都独占)
//下面一段代码问题很大。get() 只负责读取数据，也被设计成独占了
class Counter {
    private final Lock lock = new ReentrantLock();
    private int[] counts = new int[10];

    public void inc(int index) {
        lock.lock();
        try {
            counts[index] += 1;
        } finally {
            lock.unlock();
        }
    }

    public int[] get() {
        lock.lock();
        try {
            return Arrays.copyOf(counts, counts.length);
        } finally {
            lock.unlock();
        }
    }
}

//使用ReadWriteLock来实现：允许多个线程同时读，但只要有一个线程在写，其他线程就必须等待
class Counter2 {
    private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
    private final Lock rlock = rwlock.readLock();
    private final Lock wlock = rwlock.writeLock();
    private int[] counts = new int[10];

    public void inc(int index) {
        wlock.lock(); // 加写锁
        try {
            counts[index] += 1;
        } finally {
            wlock.unlock(); // 释放写锁
        }
    }

    public int[] get() {
        rlock.lock(); // 加读锁
        try {
            return Arrays.copyOf(counts, counts.length);
        } finally {
            rlock.unlock(); // 释放读锁
        }
    }
}